import fs from 'fs'
import path from 'path'
import axios from 'axios'
import yaml from 'yaml'

/** 此为向日葵创作的相对稳定的签名监测插件 **/
/** 支持签名重载，签名依据token拼接链接 **/
/** 签名重复亦或是签名多余都没事，此插件逻辑相对严密，没必要扛 **/
/** 最后祝各位新年快乐！ **/
/** 不喜欢别用，别叫，耳朵嫌吵 **/

const SIGN_SERVER_LIST = [
  {
    name: '抱脸#签名',
    url: 'https://zyr15r-astralqsign.hf.space?key=X'
  },
  {
    name: '赵怡然#签名1',
    url: 'https://qsign.trpgbot.com?key=miraibbs'
  },
  {
    name: '赵怡然#签名2',
    url: 'http://qsign-v3.trpgbot.com?key=miraibbs'
  },
  {
    name: '赵怡然#签名3',
    url: 'https://qsign.chahuyun.cn?key=miraibbs'
  },
  {
    name: '赵怡然#签名4',
    url: 'http://chahuyun.cn:18888?key=miraibbs'
  },
  {
    name: '赵怡然#签名5',
    url: 'https://qsign.shigu.cc?key=miraibbs'
  },
  {
    name: '赵怡然#签名6',
    url: 'http://49.232.201.10?key=miraibbs'
  },
  {
    name: '赵怡然#签名7',
    url: 'http://45.207.209.159:3000?key=miraibbs'
  },
  {
    name: '赵怡然#签名8',
    url: 'http://183.131.51.152:7860?key=miraibbs'
  },
  {
    name: '坏叔叔的签名1',
    url: 'http://api.furinaa.net/?key=0852369'
  },
  {
    name: '坏叔叔的签名2',
    url: 'http://110.40.45.169:7890/?key=0852369'
  },
  {
    name: '雾里#签名',
    url: 'https://q-sign.wuliya.cn?key=114514'
  }
]

const errorLogFilePath = path.join(process.cwd(), 'logs', 'error.log')
let configFilePath = path.join(process.cwd(), 'config', 'config', 'bot.yaml')   // Miao-Yunzai 则指向 bot.yaml
const qqConfigPath = path.join(process.cwd(), 'config', 'config', 'qq.yaml')  // Miao-Yunzai 协议端放 qq.yaml

// ========== 全局变量 & 常量 ==========
let lastProcessedLine = 0     // 上次已处理到的日志行号
let checkingInProgress = false // 是否正在处理签名异常流程
let lastSwitchTime = 0         // 上次切换签名的时间戳
let retryCount = 0             // 已重试次数

const MAX_RETRIES = 2          // 最大重试次数
const SWITCH_COOLDOWN = 60000  // 切换签名的冷却(ms)，避免频繁切换
const ERROR_LOG_CHECK_INTERVAL = 60000   // 定时检测 error.log 的间隔
const MAX_LOG_LINES = 10000    // error.log 行数超过此值则清空
const ERROR_THRESHOLD = 8      // 一次检测新增签名异常数 >= 8 即触发

function tryExtractTokenVersion(uin) {
  if (!uin) return ''
  try {
    // 假设 data/icqq/[uin]/[uin]_token
    const tokenFilePath = path.join(process.cwd(), 'data', 'icqq', String(uin), `${uin}_token`)
    if (!fs.existsSync(tokenFilePath)) {
      return ''
    }
    const raw = fs.readFileSync(tokenFilePath, 'utf8')
    const reg = /"ver":"([\d.]+)"/
    const match = raw.match(reg)
    if (match && match[1]) {
      return match[1].trim()
    }
    return ''
  } catch (err) {
    logWithColor(`[xrk-SignChecker] tryExtractTokenVersion 出错: ${err}`, 'red')
    return ''
  }
}

function init() {
  if (!fs.existsSync(errorLogFilePath)) {
    fs.writeFileSync(errorLogFilePath, '', 'utf8')
    logWithColor('[xrk-SignChecker] 已初始化空的 error.log', 'yellow')
  }
  determineConfigPath()
  logWithColor('[xrk-SignChecker] xrk签名异常监控已启动', 'green')

  // 定时检测 error.log
  setInterval(checkErrorLogFile, ERROR_LOG_CHECK_INTERVAL)
}

function determineConfigPath() {
  const pkg = path.join(process.cwd(), 'package.json')
  if (fs.existsSync(pkg)) {
    const pkgJson = JSON.parse(fs.readFileSync(pkg, 'utf8'))
    if (pkgJson.name === 'trss-yunzai') {
      configFilePath = path.join(process.cwd(), 'config', 'ICQQ.yaml')
    } else {
      configFilePath = path.join(process.cwd(), 'config', 'config', 'bot.yaml')
    }
  }
  logWithColor(`[xrk-SignChecker] 当前签名配置文件: ${configFilePath}`, 'cyan')
}

// ========== 定时读取 error.log，如签名异常数达阈值，则尝试切换签名 ==========
function checkErrorLogFile() {
  // 延迟一点时间再执行，防止文件还没写完就读取
  setTimeout(() => {
    try {
      clearLogIfTooLarge()

      const content = fs.readFileSync(errorLogFilePath, 'utf8')
      const lines = content.split('\n')
      // 截取上次处理行号以后新增的行
      const newLines = lines.slice(lastProcessedLine)
      lastProcessedLine = lines.length
      const errorCount = newLines.filter(line =>
        line.includes('签名api异常') ||
        (line.includes('Service Unavailable') && line.includes('Signing API'))
      ).length

      // 如果本次新增的签名异常数大于阈值，触发切换流程
      if (errorCount >= ERROR_THRESHOLD) {
        logWithColor(`[xrk-SignChecker] 新增${errorCount}条签名异常(>=${ERROR_THRESHOLD})，触发切换...`, 'red')
        handleSignError()
      }
    } catch (err) {
      logWithColor(`[xrk-SignChecker] checkErrorLogFile 出错: ${err}`, 'red')
    }
  }, 200)
}

// ========== 若 error.log 行数过多则自动清空 ==========
function clearLogIfTooLarge() {
  const content = fs.readFileSync(errorLogFilePath, 'utf8')
  if (content.split('\n').length > MAX_LOG_LINES) {
    fs.writeFileSync(errorLogFilePath, '', 'utf8')
    lastProcessedLine = 0
    logWithColor('[xrk-SignChecker] error.log 过大，已自动清空', 'yellow')
  }
}

// ========== 当异常达阈值时，尝试切换签名 ==========
async function handleSignError() {
  // 若正在进行中或未到冷却时间、或重试已达上限，则直接return
  if (checkingInProgress) return
  if (Date.now() - lastSwitchTime < SWITCH_COOLDOWN) return
  if (retryCount >= MAX_RETRIES) {
    logWithColor('[xrk-SignChecker] 已达最大重试次数，停止切换', 'yellow')
    return
  }

  checkingInProgress = true
  retryCount++
  lastSwitchTime = Date.now()

  try {
    const success = await checkAndSwitchSign()
    if (success) {
      // 切换成功后，清空日志
      fs.writeFileSync(errorLogFilePath, '', 'utf8')
      lastProcessedLine = 0

      logWithColor('[xrk-SignChecker] 签名已切换', 'green')
    }
  } catch (err) {
    logWithColor(`[xrk-SignChecker] 切换签名流程异常: ${err}`, 'red')
  } finally {
    checkingInProgress = false
  }
}

// ========== 核心：获取当前协议信息 + 筛选签名服务器 + 更新配置 + 同步Bot.sig + 发消息 + 返回成功/失败 ==========
async function checkAndSwitchSign() {
  const { platformNum, platformStr, ver } = getBotProtocolInfo()
  if (ver) {
    logWithColor(`[xrk-SignChecker] 检测到token版本: ${ver}`, 'blue')
  } else {
    logWithColor('[xrk-SignChecker] 未检测到token版本', 'yellow')
  }

  logWithColor(`[xrk-SignChecker] 当前协议端: ${platformStr}, ver: ${ver || '无(未检测)'}, 开始筛选签名...`, 'blue')
  const allCandidates = []
  for (const s of SIGN_SERVER_LIST) {
    const signInfo = await getSignServerInfo(s.url)
    if (!signInfo) continue
    if (signInfo.code !== 0 || !signInfo.data || !Array.isArray(signInfo.data.support)) {
      continue
    }
    const supportList = signInfo.data.support
 
    if (platformNum === 3 && !supportList.includes('9.0.3')) {
      continue
    }
    allCandidates.push({
      name: s.name,
      url: s.url,
      support: supportList
    })
  }
  let versionSupported = []
  if (ver) {
    versionSupported = allCandidates.filter(item => item.support.includes(ver))
  }
 
  let finalCandidates = []
  if (platformNum === 3) { 
    finalCandidates = allCandidates
  } else { 
    finalCandidates = versionSupported.length ? versionSupported : allCandidates
  }

  if (!finalCandidates.length) {
    logWithColor('[xrk-SignChecker] 无可用签名服务器(可能不支持当前平台/版本)', 'red')
    return false
  }
 
  const selected = finalCandidates[Math.floor(Math.random() * finalCandidates.length)]
 
  let finalUrl = selected.url
  if (ver && selected.support.includes(ver)) {
    // 给链接加上 &ver=xxx
    const hasQuestionMark = finalUrl.includes('?') 
    finalUrl = hasQuestionMark
      ? `${finalUrl}&ver=${ver}`
      : `${finalUrl}?ver=${ver}`
  }

  logWithColor(`[xrk-SignChecker] 选中签名服务器: ${selected.name}`, 'green')
  logWithColor(`[xrk-SignChecker] 最终签名链接: ${finalUrl}`, 'cyan')

  // 7. 修改配置文件
  await updateSignConfig(finalUrl)
  // 8. 通知
  await reportSignInfo({
    name: selected.name,
    url: finalUrl,
    support: selected.support
  })

  return true
}

// ========== 发请求获取签名信息 ==========
async function getSignServerInfo(apiUrl) {
  try {
    const res = await axios.get(apiUrl, { timeout: 5000 })
    return res.data
  } catch (e) {
    return null
  }
}

// ========== 分别获取 TRSS / MIAO ==========
function getBotProtocolInfo() {
  if (configFilePath.endsWith('ICQQ.yaml')) {
    return getTrssProtocolInfo()
  } else {
    return getMiaoProtocolInfo()
  }
}

// ========== TRSS ==========
function getTrssProtocolInfo() {
  let platformNum = 2
  let platformStr = '安卓平板'
  let ver = ''

  try {
    const raw = fs.readFileSync(configFilePath, 'utf8')
    const cfg = yaml.parse(raw) || {}
    if (cfg.bot && cfg.bot.ver) {
      ver = cfg.bot.ver.trim()
    }
    if (Array.isArray(cfg.token) && cfg.token.length) {
      const arr = String(cfg.token[0]).split(':')
      const platNum = parseInt(arr[arr.length - 1]) || 1
      platformNum = platNum
      platformStr = parsePlatformType(platNum)
    }
    if (platformNum !== 3 && typeof Bot !== 'undefined' && Bot.uin) {
      const tokenVer = tryExtractTokenVersion(Bot.uin)
      if (tokenVer) {
        ver = tokenVer
      }
    }
  } catch (err) {
    logWithColor(`[xrk-SignChecker] getTrssProtocolInfo出错: ${err}`, 'red')
  }

  return { platformNum, platformStr, ver }
}

// ========== Miao ==========
function getMiaoProtocolInfo() {
  let platformNum = 2
  let platformStr = '安卓平板'
  let ver = ''

  try {
    const raw = fs.readFileSync(qqConfigPath, 'utf8')
    const cfg = yaml.parse(raw) || {}
    platformNum = parseInt(cfg.platform) || 2
    platformStr = parsePlatformType(platformNum)
    if (platformNum !== 3 && typeof Bot !== 'undefined' && Bot.uin) {
      const tokenVer = tryExtractTokenVersion(Bot.uin)
      if (tokenVer) {
        ver = tokenVer
      }
    }
  } catch (err) {
    logWithColor(`[xrk-SignChecker] getMiaoProtocolInfo出错: ${err}`, 'red')
  }

  return { platformNum, platformStr, ver }
}

// ========== 将数字平台映射成可读文字 ==========
function parsePlatformType(num) {
  switch (num) {
    case 1: return '安卓手机'
    case 2: return 'aPad'
    case 3: return '安卓手表'
    case 6: return 'Tim'
    default: return '其他协议'
  }
}

async function updateSignConfig(newSignUrl) {
  if (configFilePath.endsWith('ICQQ.yaml')) {
    const raw = fs.readFileSync(configFilePath, 'utf8')
    const cfg = yaml.parse(raw) || {}
    if (!cfg.bot) cfg.bot = {}

    if (cfg.bot.sign_api_addr !== newSignUrl) {
      cfg.bot.sign_api_addr = newSignUrl
      if (global.Bot && global.Bot.sig) {
        global.Bot.sig.sign_api_addr = newSignUrl
      }
      fs.writeFileSync(configFilePath, yaml.stringify(cfg), 'utf8')
      logWithColor(`[xrk-SignChecker] 已写入 ICQQ.yaml => sign_api_addr: ${newSignUrl}`, 'green')
    } else {
      logWithColor('[xrk-SignChecker] ICQQ.yaml 已是该签名地址，无需更新', 'yellow')
    }
  } else {
    const raw = fs.readFileSync(configFilePath, 'utf8')
    const cfg = yaml.parse(raw) || {}
    if (cfg.sign_api_addr !== newSignUrl) {
      cfg.sign_api_addr = newSignUrl
      if (global.Bot && global.Bot.sig) {
        global.Bot.sig.sign_api_addr = newSignUrl
      }
      fs.writeFileSync(configFilePath, yaml.stringify(cfg), 'utf8')
      logWithColor(`[xrk-SignChecker] 已写入 bot.yaml => sign_api_addr: ${newSignUrl}`, 'green')
    } else {
      logWithColor('[xrk-SignChecker] bot.yaml 已是该签名地址，无需更新', 'yellow')
    }
  }
}

// ========== 切换成功后向主人发送信息 ==========
async function reportSignInfo(selected) {
  const { name, url, support } = selected
  const sup = support.join(', ')
  let msg = '【xrk签名切换通知】\n'
  msg += `\n已切换到签名：${name}\n`
  msg += `签名地址：${url}\n`
  msg += `支持版本：${sup || '无'}\n`
  msg += '\n已自动重载新签名，如若后台仍旧出现大量报错，请自行重启，最后祝愿各位新年快乐'
  if (typeof Bot !== 'undefined' && Bot.sendMasterMsg) {
    Bot.sendMasterMsg(msg)
  }
}

// ========== 带时间戳 + 颜色输出 ==========
function logWithColor(text, color = 'reset') {
  const timestamp = new Date().toLocaleString()
  const colors = {
    reset:  '\x1b[0m',
    red:    '\x1b[31m',
    green:  '\x1b[32m',
    yellow: '\x1b[33m',
    blue:   '\x1b[34m',
    cyan:   '\x1b[36m'
  }
  console.log(`${colors[color] || ''}[${timestamp}] ${text}${colors.reset}`)
}

export class xrkSignCheckerPlugin extends plugin {
  constructor() {
    super({
      name: 'xrk-SignChecker',
      dsc: '大量签名异常自动切换',
      event: 'system',
      priority: 10,
      rule: []
    })
  }
  async init() {
    init()
  }
}